﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TAD
{
    /// <summary>
    /// 
    /// </summary>
    public class Pilha
    {

        #region Locals
        private object[] _array;   //contém os objetos que vão ser armazenados na pilha
        private byte[] _arraybytes;   //contém os objetos que vão ser armazenados na pilha     
        private const int _defaultCapacity = 53;
        private int _size;  //tamanho da Pilha, utilizado na sobrecarga do construtor


        [NonSerialized]
        private int _version;

        #endregion

        #region Methods


        /// <summary>
        /// Construtor padrão
        /// </summary>
        public Pilha()
        {
            this._array = new object[10];
            this._size = 0;
            this._version = 0;
        }

        public Pilha(byte objs)
        {
            this._arraybytes = new byte[10];
            this._size = 0;
            this._version = 0;
        }


       /// <summary>
       /// Sobrecarga do construtor
       /// </summary>
       /// <param name="initialCapacity">Número de elementos que devem ser armazenados</param>
        public Pilha(int initialCapacity)
        {
            if (initialCapacity < 0)
            {
                throw new ArgumentOutOfRangeException("O valor da capacidade da pilha não pode ser negativo");
            }
            if (initialCapacity < 53)
            {
                initialCapacity = 53;
            }
            this._array = new object[initialCapacity];
            this._size = 0;
            this._version = 0;
        }

        /// <summary>
        /// Método utilizado para remover um item da pilha
        /// </summary>
        /// <returns></returns>
        public virtual object Pop()
        {
            if (this._size == 0)
            {
                throw new InvalidOperationException("A pilha está vazia");
            }
            this._version++;
            object obj2 = this._array[--this._size];
            this._array[this._size] = null;
            return obj2;
        }

        /// <summary>
        /// Método utilizado para incluir um novo objeto na pilha
        /// </summary>
        /// <param name="obj"></param>
        public virtual void Push(object obj)
        {
            if (this._size == this._array.Length)
            {
                object[] destinationArray = new object[2 * this._array.Length];
                Array.Copy(this._array, 0, destinationArray, 0, this._size);
                this._array = destinationArray;
            }
            this._array[this._size++] = obj;
            this._version++;
        }    

        /// <summary>
        /// Utilizado apar limpar a coleção de itens da pilha
        /// </summary>
        public virtual void Clear()
        {
            Array.Clear(this._array, 0, this._size);
            this._size = 0;
            this._version++;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="array"></param>
        /// <param name="index"></param>
        public virtual void CopyTo(Array array, int index)
        {
            if (array == null)
            {
                throw new ArgumentNullException("array");
            }
            if (array.Rank != 1)
            {
                throw new ArgumentException("multidimensões não suportado");
            }
            if (index < 0)
            {
                throw new ArgumentOutOfRangeException("O número não pode ser negativo");
            }
            if ((array.Length - index) < this._size)
            {
                throw new ArgumentException("valor inválido");
            }
            int num = 0;
            if (array is object[])
            {
                object[] objArray = (object[])array;
                while (num < this._size)
                {
                    objArray[num + index] = this._array[(this._size - num) - 1];
                    num++;
                }
            }
            else
            {
                while (num < this._size)
                {
                    array.SetValue(this._array[(this._size - num) - 1], (int)(num + index));
                    num++;
                }
            }
        }



        #endregion

        #region Properties

        /// <summary>
        /// Retorna a quantidade atual de itens na pilha
        /// </summary>
        public virtual int Count
        {
            get
            {
                return this._size;
            }
        }

        #endregion



    }
}
